package org.javaymw.springboot.controller.activiti.controller;

import com.alibaba.fastjson.JSONObject;
import org.javaymw.springboot.util.MessageUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: zhaoxinguo
 * @Date: 2018/10/19 11:35
 * @Description: 流程管理
 */
@Controller
@RequestMapping("/admin/processInstance")
public class ProcessInstanceController extends AbstractActivitiController {

    /**
     * 查询运行中的流程实例列表
     *
     * @return
     */
    @RequestMapping(value = "/runing")
    public String runingProcess(org.springframework.ui.Model model) {
        List list = new ArrayList<>();
        // 创建流程实例查询对象
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        // 根据流程实例id排序，降序
        processInstanceQuery.orderByProcessInstanceId().desc();
        // 执行查询，获得流程实例列表数据
        List<ProcessInstance> processInstanceList = processInstanceQuery.list();
        for (ProcessInstance processInstance : processInstanceList) {
            Map map=new HashMap<>();
            map.put("id",processInstance.getId());
            map.put("name",processInstance.getName());
            map.put("definitionId",processInstance.getProcessDefinitionId());
            map.put("deploymentId",processInstance.getDeploymentId());
            map.put("activityId",processInstance.getActivityId());
            map.put("nodeName","");
            map.put("suspended",processInstance.isSuspended());
            // 取当前节点
            ProcessDefinitionEntity entity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getProcessDefinition(processInstance.getProcessDefinitionId());
            for (ActivityImpl bean :entity.getActivities()){
                if (bean.getId().equals(processInstance.getActivityId())){
                    map.put("nodeName",bean.getProperty("name"));
                }
            }
            list.add(map);
        }
        model.addAttribute("list", list);
        return "admin/workflow/processInstanceList";
    }

    /**
     * 根据流程实例id查询对应的流程变量数据
     * @return
     */
    @RequestMapping(value = "/findProcessVariables/{processInstanceId}")
    @ResponseBody
    public Map<String, Object> findProcessVariables(@PathVariable("processInstanceId") String processInstanceId) {
        Map<String, Object> retMap = null;
        try {
            Map<String, Object> variables = runtimeService.getVariables(processInstanceId);
            retMap = MessageUtils.success();
            // 返回流程变量数据
            retMap.put("variables", variables);
        } catch (Exception e) {
            LOGGER.error("根据流程实例id查询对应的流程变量数据失败：processInstanceId={}", processInstanceId, e);
            retMap = MessageUtils.error();
        }
        return retMap;
    }

    /**
     * 挂起、激活流程实例
     */
    @RequestMapping(value = "/update/{state}/{processInstanceId}")
    @ResponseBody
    public Map<String, Object> updateState(@PathVariable("state") String state,
                                           @PathVariable("processInstanceId") String processInstanceId,
                                           RedirectAttributes redirectAttributes) {
        Map<String, Object> retMap = null;
        try {
            if (state.equals("active")) {
                redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processInstanceId + "]的流程实例。");
                runtimeService.activateProcessInstanceById(processInstanceId);
                retMap = MessageUtils.success("激活成功");
            } else if (state.equals("suspend")) {
                runtimeService.suspendProcessInstanceById(processInstanceId);
                redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processInstanceId + "]的流程实例。");
                retMap = MessageUtils.success("挂起成功");
            }
        } catch (Exception e) {
            LOGGER.error("挂起、激活流程实例失败：processInstanceId={}", processInstanceId, e);
            retMap = MessageUtils.error();
        }
        return retMap;
    }

    /**
     * 根据流程实例ID 读取带跟踪的图片
     * @param processInstanceId 流程实例ID
     * @return
     */
    @RequestMapping(value = "/trace/{processInstanceId}")
    @ResponseBody
    public String readResource(@PathVariable("processInstanceId") String processInstanceId) {
        try {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
            List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstanceId);

            // 不使用spring请使用下面的两行代码
            /*ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
            Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());*/

            // 使用spring注入引擎请使用下面的这行代码
            processEngineConfiguration = processEngine.getProcessEngineConfiguration();
            Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

            ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
            InputStream imageStream = diagramGenerator.generateDiagram(
                    bpmnModel,
                    "png",
                    activeActivityIds,
                    new ArrayList<String>(),
                    "宋体",
                    "宋体",
                    "宋体",
                    null,
                    1.0);
            // 输出资源内容到相应对象

            // 输入流转二进制
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] data = new byte[4096];
            int count = 1;
            while ((count = imageStream.read(data, 0, 4096)) != -1) {
                byteArrayOutputStream.write(data, 0, count);
            }
            byte[] bytes = byteArrayOutputStream.toByteArray();

            return JSONObject.toJSONString(bytes);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("根据流程实例ID 读取带跟踪的图片失败：processInstanceId={}", processInstanceId, e);
        }
        return null;
    }

    /**
     * 根据流程实例ID批量删除进行中的流程实例
     *
     * @param ids
     * @return
     */
    @PostMapping(value = "/deleteBatch")
    @ResponseBody
    public Map<String, Object> deleteBatch(@RequestParam("ids[]") List<String> ids) {
        Map<String, Object> retMap = null;
        try {
            ids.forEach(id -> {
                runtimeService.deleteProcessInstance(id, "批量删除流程实例[" + id + "]");
            });
            retMap = MessageUtils.success("批量删除成功");
        } catch (Exception e) {
            retMap = MessageUtils.error();
        }
        return retMap;
    }
}
